{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def loadDataSet():\n",
    "    return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]\n",
    "\n",
    "# 创建的C1是大小为1的所有候选项的集合\n",
    "def createC1(dataSet):\n",
    "    C1 = []\n",
    "    for transaction in dataSet:  # 遍历每一个项集\n",
    "        for item in transaction:  # 遍历项集中的每一个项\n",
    "            if not [item] in C1:\n",
    "                C1.append([item])\n",
    "    C1.sort()\n",
    "    return list(map(frozenset, C1))\n",
    "\n",
    "# 用于从C1生成L1（满足最小支持度的项集），以及包含支持度值的字典以备后用\n",
    "# 参数：包含候选集合的列表D，数据集Ck，以及感兴趣集的最小支持度minSupport\n",
    "# 返回值：保存满足最小支持度的数据列表retList，支持度字典\n",
    "def scanD(D, Ck, minSupport):\n",
    "    ssCnt = {}  # 记录每个数据在所有项集中出现的次数\n",
    "    for tid in D:  # 遍历每一个项集\n",
    "        for can in Ck:  # 遍历每一个数据\n",
    "            if can.issubset(tid):  # 如果数据是项集i的子集，则该数据支持度+1\n",
    "                if can not in ssCnt:\n",
    "                    ssCnt[can] = 1\n",
    "                else:\n",
    "                    ssCnt[can] += 1\n",
    "    numItems = float(len(D))  # 求项集数量\n",
    "    retList = []\n",
    "    supportData = {}\n",
    "    for key in ssCnt:  # 遍历每一个数据\n",
    "        support = ssCnt[key] / numItems  # 计算支持度\n",
    "        if support >= minSupport:\n",
    "            retList.insert(0, key)\n",
    "        supportData[key] = support\n",
    "    return retList, supportData"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataSet = loadDataSet()\n",
    "dataSet"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[frozenset({1}),\n",
       " frozenset({2}),\n",
       " frozenset({3}),\n",
       " frozenset({4}),\n",
       " frozenset({5})]"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "C1 = createC1(dataSet)\n",
    "C1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{1, 3, 4}, {2, 3, 5}, {1, 2, 3, 5}, {2, 5}]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 求得不重复的候选集合列表\n",
    "D = list(map(set, dataSet))\n",
    "D"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L1, suppData0  = scanD(D, C1, 0.5)\n",
    "L1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建候选集Ck\n",
    "# 参数：频繁项集列表Lk，项集元素个数k\n",
    "# 举例：该函数输入{0},{1},{2}，则会生成{0,1},{0,2},{1,2}（k=2）\n",
    "def aprioriGen(Lk, k):\n",
    "    retList = []\n",
    "    lenLk = len(Lk)\n",
    "#     print(Lk, k)\n",
    "    for i in range(lenLk):\n",
    "        for j in range(i+1, lenLk):\n",
    "            L1 = list(Lk[i])[:k-2]\n",
    "#             print('L1: ', L1)\n",
    "            L2 = list(Lk[j])[:k-2]\n",
    "#             print('L2: ', L2)\n",
    "            L1.sort()\n",
    "            L2.sort()\n",
    "            if L1 == L2:\n",
    "                retList.append(Lk[i] | Lk[j])\n",
    "#     print('retList: ', retList)\n",
    "#     print('==================================================')\n",
    "    return retList\n",
    "\n",
    "# 返回频繁项集列表，支持度字典\n",
    "def apriori(dataSet, minSupport=0.5):\n",
    "    C1 = createC1(dataSet)\n",
    "    D = list(map(set, dataSet))\n",
    "    L1, supportData = scanD(D, C1, minSupport)\n",
    "    L = [L1]\n",
    "    k = 2\n",
    "    while len(L[k-2]) > 0:\n",
    "        Ck = aprioriGen(L[k-2], k)\n",
    "        Lk, supK = scanD(D, Ck, minSupport)\n",
    "        supportData.update(supK)\n",
    "        L.append(Lk)\n",
    "        k += 1\n",
    "    return L, supportData"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})],\n",
       " [frozenset({2, 3}), frozenset({3, 5}), frozenset({2, 5}), frozenset({1, 3})],\n",
       " [frozenset({2, 3, 5})],\n",
       " []]"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L, suppData = apriori(dataSet)\n",
    "L"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[frozenset({5}), frozenset({2}), frozenset({3}), frozenset({1})]"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[frozenset({2, 3}), frozenset({3, 5}), frozenset({2, 5}), frozenset({1, 3})]"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L[1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[frozenset({2, 3, 5})]"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L[2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L[3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[frozenset({2, 5}),\n",
       " frozenset({3, 5}),\n",
       " frozenset({1, 5}),\n",
       " frozenset({2, 3}),\n",
       " frozenset({1, 2}),\n",
       " frozenset({1, 3})]"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "aprioriGen(L[0], 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[frozenset({5}), frozenset({2}), frozenset({3})], [frozenset({2, 5})], []]"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L, suppData = apriori(dataSet, 0.7)\n",
    "L"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 参数：频繁项集列表，包含那些频繁项集支持数据的字典，最小可信度阈值\n",
    "# 返回：包含可信度的规则列表\n",
    "def generateRules(L, supportData, minConf=0.7):\n",
    "    bigRuleList = []\n",
    "    for i in range(1, len(L)):\n",
    "        for freqSet in L[i]:  # 从第2个（第1个都是单个元素没有意义）开始遍历频繁列表\n",
    "#             print(freqSet)\n",
    "            H1 = [frozenset([item]) for item in freqSet]  # 将freqSet每项的元素存为列表\n",
    "#             print(H1)\n",
    "            if i > 1:  # 如果频繁项超过2则计算其是否可继续分\n",
    "                rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)\n",
    "            else:\n",
    "                calcConf(freqSet, H1, supportData, bigRuleList, minConf)\n",
    "    return bigRuleList\n",
    "\n",
    "# 对规则进行评估\n",
    "def calcConf(freqSet, H, supportData, br1, minConf=0.7):\n",
    "    prunedH = []  # 记录通过评估的元素\n",
    "    for conseq in H:\n",
    "        conf = supportData[freqSet] / supportData[freqSet - conseq]  # 计算可信度\n",
    "        if conf >= minConf:\n",
    "#             print(freqSet, conseq)\n",
    "#             print(freqSet - conseq, '-->', conseq, 'conf: ', conf)\n",
    "            br1.append((freqSet - conseq, conseq, conf))  # 填充规则列表\n",
    "            prunedH.append(conseq)\n",
    "    return prunedH\n",
    "\n",
    "# 生成候选规则集合\n",
    "def rulesFromConseq(freqSet, H, supportData, br1, minConf=0.7):\n",
    "    m = len(H[0])  # 每个频繁项的大小\n",
    "    if len(freqSet) > m + 1:\n",
    "        Hmp1 = aprioriGen(H, m+1)\n",
    "        Hmp1 = calcConf(freqSet, Hmp1, supportData, br1, minConf)\n",
    "        if len(Hmp1) > 1:\n",
    "            rulesFromConseq(freqSet, Hmp1, supportData, br1, minConf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "frozenset({5}) --> frozenset({2}) conf:  1.0\n",
      "frozenset({2}) --> frozenset({5}) conf:  1.0\n",
      "frozenset({1}) --> frozenset({3}) conf:  1.0\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[(frozenset({5}), frozenset({2}), 1.0),\n",
       " (frozenset({2}), frozenset({5}), 1.0),\n",
       " (frozenset({1}), frozenset({3}), 1.0)]"
      ]
     },
     "execution_count": 88,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L, suppData = apriori(dataSet, minSupport=0.5)\n",
    "rules = generateRules(L, suppData, minConf=0.7)\n",
    "rules"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "frozenset({3}) --> frozenset({2}) conf:  0.6666666666666666\n",
      "frozenset({2}) --> frozenset({3}) conf:  0.6666666666666666\n",
      "frozenset({5}) --> frozenset({3}) conf:  0.6666666666666666\n",
      "frozenset({3}) --> frozenset({5}) conf:  0.6666666666666666\n",
      "frozenset({5}) --> frozenset({2}) conf:  1.0\n",
      "frozenset({2}) --> frozenset({5}) conf:  1.0\n",
      "frozenset({3}) --> frozenset({1}) conf:  0.6666666666666666\n",
      "frozenset({1}) --> frozenset({3}) conf:  1.0\n",
      "frozenset({5}) --> frozenset({2, 3}) conf:  0.6666666666666666\n",
      "frozenset({3}) --> frozenset({2, 5}) conf:  0.6666666666666666\n",
      "frozenset({2}) --> frozenset({3, 5}) conf:  0.6666666666666666\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[(frozenset({3}), frozenset({2}), 0.6666666666666666),\n",
       " (frozenset({2}), frozenset({3}), 0.6666666666666666),\n",
       " (frozenset({5}), frozenset({3}), 0.6666666666666666),\n",
       " (frozenset({3}), frozenset({5}), 0.6666666666666666),\n",
       " (frozenset({5}), frozenset({2}), 1.0),\n",
       " (frozenset({2}), frozenset({5}), 1.0),\n",
       " (frozenset({3}), frozenset({1}), 0.6666666666666666),\n",
       " (frozenset({1}), frozenset({3}), 1.0),\n",
       " (frozenset({5}), frozenset({2, 3}), 0.6666666666666666),\n",
       " (frozenset({3}), frozenset({2, 5}), 0.6666666666666666),\n",
       " (frozenset({2}), frozenset({3, 5}), 0.6666666666666666)]"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rules = generateRules(L, suppData, minConf=0.5)\n",
    "rules"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 实例：发现毒蘑菇的相似特征"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['1',\n",
       " '3',\n",
       " '9',\n",
       " '13',\n",
       " '23',\n",
       " '25',\n",
       " '34',\n",
       " '36',\n",
       " '38',\n",
       " '40',\n",
       " '52',\n",
       " '54',\n",
       " '59',\n",
       " '63',\n",
       " '67',\n",
       " '76',\n",
       " '85',\n",
       " '86',\n",
       " '90',\n",
       " '93',\n",
       " '98',\n",
       " '107',\n",
       " '113']"
      ]
     },
     "execution_count": 104,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mushDatSet = [line.split() for line in open('mushroom.dat').readlines()]\n",
    "mushDatSet[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "frozenset({'28', '2'})\n",
      "frozenset({'2', '53'})\n",
      "frozenset({'23', '2'})\n",
      "frozenset({'34', '2'})\n",
      "frozenset({'36', '2'})\n",
      "frozenset({'59', '2'})\n",
      "frozenset({'63', '2'})\n",
      "frozenset({'67', '2'})\n",
      "frozenset({'76', '2'})\n",
      "frozenset({'85', '2'})\n",
      "frozenset({'86', '2'})\n",
      "frozenset({'90', '2'})\n",
      "frozenset({'93', '2'})\n",
      "frozenset({'39', '2'})\n"
     ]
    }
   ],
   "source": [
    "L, suppData = apriori(mushDatSet, minSupport=0.3)\n",
    "for item in L[1]:\n",
    "    # intersection() 方法用于返回两个或更多集合中都包含的元素，即交集\n",
    "    if item.intersection('2'):  \n",
    "        print(item)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "frozenset({'28', '34', '59', '2'})\n",
      "frozenset({'28', '34', '85', '2'})\n",
      "frozenset({'28', '34', '86', '2'})\n",
      "frozenset({'28', '34', '2', '53'})\n",
      "frozenset({'28', '34', '63', '2'})\n",
      "frozenset({'28', '59', '63', '2'})\n",
      "frozenset({'28', '85', '63', '2'})\n",
      "frozenset({'28', '63', '86', '2'})\n",
      "frozenset({'28', '85', '59', '2'})\n",
      "frozenset({'28', '85', '86', '2'})\n",
      "frozenset({'28', '2', '85', '53'})\n",
      "frozenset({'28', '59', '86', '2'})\n",
      "frozenset({'28', '2', '86', '53'})\n",
      "frozenset({'90', '28', '53', '2'})\n",
      "frozenset({'90', '28', '39', '2'})\n",
      "frozenset({'90', '28', '34', '2'})\n",
      "frozenset({'90', '28', '2', '59'})\n",
      "frozenset({'90', '28', '85', '2'})\n",
      "frozenset({'90', '28', '86', '2'})\n",
      "frozenset({'28', '53', '39', '2'})\n",
      "frozenset({'28', '34', '39', '2'})\n",
      "frozenset({'28', '59', '39', '2'})\n",
      "frozenset({'28', '39', '63', '2'})\n",
      "frozenset({'28', '85', '39', '2'})\n",
      "frozenset({'28', '39', '86', '2'})\n",
      "frozenset({'34', '2', '85', '53'})\n",
      "frozenset({'34', '2', '86', '53'})\n",
      "frozenset({'2', '85', '86', '53'})\n",
      "frozenset({'90', '2', '39', '53'})\n",
      "frozenset({'90', '34', '2', '53'})\n",
      "frozenset({'90', '2', '85', '53'})\n",
      "frozenset({'90', '2', '86', '53'})\n",
      "frozenset({'34', '2', '39', '53'})\n",
      "frozenset({'2', '85', '39', '53'})\n",
      "frozenset({'2', '39', '86', '53'})\n",
      "frozenset({'23', '59', '63', '2'})\n",
      "frozenset({'23', '85', '63', '2'})\n",
      "frozenset({'23', '63', '86', '2'})\n",
      "frozenset({'23', '85', '59', '2'})\n",
      "frozenset({'23', '85', '86', '2'})\n",
      "frozenset({'23', '85', '93', '2'})\n",
      "frozenset({'23', '59', '86', '2'})\n",
      "frozenset({'23', '93', '59', '2'})\n",
      "frozenset({'23', '93', '86', '2'})\n",
      "frozenset({'34', '23', '59', '2'})\n",
      "frozenset({'34', '23', '85', '2'})\n",
      "frozenset({'34', '23', '86', '2'})\n",
      "frozenset({'34', '23', '93', '2'})\n",
      "frozenset({'34', '23', '63', '2'})\n",
      "frozenset({'34', '59', '63', '2'})\n",
      "frozenset({'34', '85', '63', '2'})\n",
      "frozenset({'34', '63', '86', '2'})\n",
      "frozenset({'34', '93', '63', '2'})\n",
      "frozenset({'34', '85', '59', '2'})\n",
      "frozenset({'34', '85', '86', '2'})\n",
      "frozenset({'34', '85', '93', '2'})\n",
      "frozenset({'34', '59', '86', '2'})\n",
      "frozenset({'34', '93', '59', '2'})\n",
      "frozenset({'34', '93', '86', '2'})\n",
      "frozenset({'23', '34', '36', '2'})\n",
      "frozenset({'23', '59', '36', '2'})\n",
      "frozenset({'23', '85', '36', '2'})\n",
      "frozenset({'23', '36', '86', '2'})\n",
      "frozenset({'23', '93', '36', '2'})\n",
      "frozenset({'34', '59', '36', '2'})\n",
      "frozenset({'34', '85', '36', '2'})\n",
      "frozenset({'34', '36', '86', '2'})\n",
      "frozenset({'34', '93', '36', '2'})\n",
      "frozenset({'23', '36', '63', '2'})\n",
      "frozenset({'34', '36', '63', '2'})\n",
      "frozenset({'59', '36', '63', '2'})\n",
      "frozenset({'85', '36', '63', '2'})\n",
      "frozenset({'36', '63', '86', '2'})\n",
      "frozenset({'93', '36', '63', '2'})\n",
      "frozenset({'85', '59', '36', '2'})\n",
      "frozenset({'85', '36', '86', '2'})\n",
      "frozenset({'85', '93', '36', '2'})\n",
      "frozenset({'59', '36', '86', '2'})\n",
      "frozenset({'93', '59', '36', '2'})\n",
      "frozenset({'93', '36', '86', '2'})\n",
      "frozenset({'85', '59', '63', '2'})\n",
      "frozenset({'85', '63', '86', '2'})\n",
      "frozenset({'85', '93', '63', '2'})\n",
      "frozenset({'59', '63', '86', '2'})\n",
      "frozenset({'93', '59', '63', '2'})\n",
      "frozenset({'93', '63', '86', '2'})\n",
      "frozenset({'34', '85', '67', '2'})\n",
      "frozenset({'34', '67', '86', '2'})\n",
      "frozenset({'85', '67', '86', '2'})\n",
      "frozenset({'34', '85', '76', '2'})\n",
      "frozenset({'34', '76', '86', '2'})\n",
      "frozenset({'85', '76', '86', '2'})\n",
      "frozenset({'85', '59', '86', '2'})\n",
      "frozenset({'85', '93', '86', '2'})\n",
      "frozenset({'85', '93', '59', '2'})\n",
      "frozenset({'90', '23', '34', '2'})\n",
      "frozenset({'90', '23', '59', '2'})\n",
      "frozenset({'90', '23', '85', '2'})\n",
      "frozenset({'90', '23', '86', '2'})\n",
      "frozenset({'90', '23', '93', '2'})\n",
      "frozenset({'90', '34', '36', '2'})\n",
      "frozenset({'90', '34', '59', '2'})\n",
      "frozenset({'90', '34', '63', '2'})\n",
      "frozenset({'90', '34', '85', '2'})\n",
      "frozenset({'90', '34', '86', '2'})\n",
      "frozenset({'90', '34', '93', '2'})\n",
      "frozenset({'90', '59', '36', '2'})\n",
      "frozenset({'90', '36', '63', '2'})\n",
      "frozenset({'90', '85', '36', '2'})\n",
      "frozenset({'90', '36', '86', '2'})\n",
      "frozenset({'90', '93', '36', '2'})\n",
      "frozenset({'90', '59', '63', '2'})\n",
      "frozenset({'90', '85', '63', '2'})\n",
      "frozenset({'90', '63', '86', '2'})\n",
      "frozenset({'90', '93', '63', '2'})\n",
      "frozenset({'90', '85', '59', '2'})\n",
      "frozenset({'90', '85', '86', '2'})\n",
      "frozenset({'90', '85', '93', '2'})\n",
      "frozenset({'90', '59', '86', '2'})\n",
      "frozenset({'90', '93', '59', '2'})\n",
      "frozenset({'90', '93', '86', '2'})\n",
      "frozenset({'93', '59', '86', '2'})\n",
      "frozenset({'23', '34', '39', '2'})\n",
      "frozenset({'23', '59', '39', '2'})\n",
      "frozenset({'23', '85', '39', '2'})\n",
      "frozenset({'23', '39', '86', '2'})\n",
      "frozenset({'23', '93', '39', '2'})\n",
      "frozenset({'34', '59', '39', '2'})\n",
      "frozenset({'34', '85', '39', '2'})\n",
      "frozenset({'34', '39', '86', '2'})\n",
      "frozenset({'34', '93', '39', '2'})\n",
      "frozenset({'23', '39', '36', '2'})\n",
      "frozenset({'34', '39', '36', '2'})\n",
      "frozenset({'2', '39', '36', '59'})\n",
      "frozenset({'39', '36', '63', '2'})\n",
      "frozenset({'85', '39', '36', '2'})\n",
      "frozenset({'39', '36', '86', '2'})\n",
      "frozenset({'93', '39', '36', '2'})\n",
      "frozenset({'23', '39', '63', '2'})\n",
      "frozenset({'34', '39', '63', '2'})\n",
      "frozenset({'59', '39', '63', '2'})\n",
      "frozenset({'85', '39', '63', '2'})\n",
      "frozenset({'39', '63', '86', '2'})\n",
      "frozenset({'93', '39', '63', '2'})\n",
      "frozenset({'34', '67', '39', '2'})\n",
      "frozenset({'85', '67', '39', '2'})\n",
      "frozenset({'67', '39', '86', '2'})\n",
      "frozenset({'34', '76', '39', '2'})\n",
      "frozenset({'85', '76', '39', '2'})\n",
      "frozenset({'76', '39', '86', '2'})\n",
      "frozenset({'85', '59', '39', '2'})\n",
      "frozenset({'85', '39', '86', '2'})\n",
      "frozenset({'85', '93', '39', '2'})\n",
      "frozenset({'59', '39', '86', '2'})\n",
      "frozenset({'90', '34', '39', '2'})\n",
      "frozenset({'90', '36', '39', '2'})\n",
      "frozenset({'90', '2', '39', '59'})\n",
      "frozenset({'90', '39', '63', '2'})\n",
      "frozenset({'90', '85', '39', '2'})\n",
      "frozenset({'90', '39', '86', '2'})\n",
      "frozenset({'90', '93', '39', '2'})\n",
      "frozenset({'93', '59', '39', '2'})\n",
      "frozenset({'93', '39', '86', '2'})\n"
     ]
    }
   ],
   "source": [
    "# 可以对更大的项集来观测\n",
    "for item in L[3]:\n",
    "    # intersection() 方法用于返回两个或更多集合中都包含的元素，即交集\n",
    "    if item.intersection('2'):  \n",
    "        print(item)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
